<template>
  <div class="containers">
    <div id="canvas"></div>
    <properties-view v-if="bpmnModeler" :modeler="bpmnModeler"></properties-view>
    <ul class="buttons">
      <li>
        <a @click="$refs.refFile.click()">加载本地BPMN文件</a>
        <input
          type="file"
          id="files"
          ref="refFile"
          style="display: none"
          @change="loadXML"
        />
      </li>
      <li>
        <a @click="downloadDiagram($event)">BPMN</a>
      </li>
      <li>
        <a @click="downloadSvg($event)">SVG</a>
      </li>
      <li>
        <a  @click="handlerUndo">撤销</a>
      </li>
      <li>
        <a @click="handlerRedo">恢复</a>
      </li>
      <li>
        <a @click="handlerZoom(0.1)">放大</a>
      </li>
      <li>
        <a @click="handlerZoom(-0.1)">缩小</a>
      </li>
      <li>
        <a  @click="handlerZoom(0)">还原</a>
      </li>
    </ul>
  </div>
</template>

<script>

import { onMounted, reactive, toRefs } from 'vue'
import BpmnModeler from 'bpmn-js/lib/Modeler'
import { xmlStr } from '../mock/xmlStrViewer'
import { debounce } from 'min-dash'
import PropertiesView from '../custom-properties-panel/PropertiesView'
export default {
  name: 'BpmnModeler',
  components: {
    PropertiesView
  },
  setup () {
    const state = reactive({
      xmlStr: '',
      bpmnModeler: null,
      svg: '',
      xml: '',
      canvas: null,
      scale: 1
    })
    onMounted(() => {
      state.bpmnModeler = new BpmnModeler({
        container: '#canvas',
        additionalModules: [
          {
            // 禁用左侧面板
            paletteProvider: ['value', ''],

            // 禁用滚轮滚动
            zoomScroll: ['value', ''],
            // 禁止拖动线
            bendpoints: ['value', ''],

            // 禁止点击节点出现contextPad
            contextPadProvider: ['value', ''],
            // 禁止双击节点出现label编辑框
            labelEditingProvider: ['value', '']
          }]
      })

      state.xmlStr = xmlStr
      init(state.xmlStr)
    })

    const changedEvent = debounce(async function () {
      try {
        const { svg } = await state.bpmnModeler.saveSVG()
        state.svg = encodeURIComponent(svg)
      } catch (err) {
        state.svg = ''
      }

      try {
        const { xml } = await state.bpmnModeler.saveXML({ format: true })
        state.xml = encodeURIComponent(xml)
      } catch (err) {
        state.xml = ''
      }
    }, 500)

    // const clickEvent = (e) => {
    //   const modeling = state.bpmnModeler.get('modeling')
    //   const elementRegistry = state.bpmnModeler.get('elementRegistry')
    //   if (!e || e.element.type === 'bpmn:Process' || e.element.type === 'bpmn:SequenceFlow' || e.element.type === 'label') return
    //   const shape = e.element ? elementRegistry.get(e.element.id) : e.shape
    //   if (shape.type === 'bpmn:StartEvent') {
    //     modeling.updateProperties(shape, {
    //       name: '我是修改后的虚线节点',
    //       isInterrupting: false,
    //       customText: '我是自定义的text属性'
    //     })
    //     modeling.setColor(shape, {
    //       fill: '#ff0000',
    //       stroke: null
    //     })
    //   }
    // }
    //
    // const hoverEvent = (e) => {
    //   const overlays = state.bpmnModeler.get('overlays')
    //   const elementRegistry = state.bpmnModeler.get('elementRegistry')
    //   if (!e || e.element.type === 'bpmn:Process' || e.element.type === 'bpmn:SequenceFlow' || e.element.type === 'label') return
    //   const shape = e.element ? elementRegistry.get(e.element.id) : e.shape
    //   const layDiv = '<div class="highlight-overlay" style="width: ' + shape.width * 2 + 'px;height: ' + shape.height * 2 + 'px"></div>'
    //   overlays.add(shape.id, {
    //     position: {
    //       bottom: shape.height,
    //       right: shape.width
    //     },
    //     html: layDiv
    //   })
    // }
    //
    // const outEvent = (e) => {
    //   const overlays = state.bpmnModeler.get('overlays')
    //   const elementRegistry = state.bpmnModeler.get('elementRegistry')
    //   if (!e || e.element.type === 'bpmn:Process' || e.element.type === 'bpmn:SequenceFlow' || e.element.type === 'label') return
    //   const shape = e.element ? elementRegistry.get(e.element.id) : e.shape
    //   overlays.remove({ element: shape.id })
    // }

    const init = (xmls) => {
      state.bpmnModeler.importXML(xmls).then(function () {
        state.canvas = state.bpmnModeler.get('canvas')
        state.canvas.zoom('fit-viewport', 'auto')
        // // 标记颜色（1）
        // markColor1()
        // // 标记颜色（2）--- 页面撤销按钮会产生效果
        // markColor2()
        // // 标记颜色（3）---延迟且无法点击
        // markColor3()
        // // 绑定流程设计变化事件
        state.bpmnModeler.on('commandStack.changed', changedEvent)
        // state.bpmnModeler.on('element.click', (event) => clickEvent(event))
        // state.bpmnModeler.on('element.hover', (event) => hoverEvent(event))
        // state.bpmnModeler.on('element.out', (event) => outEvent(event))
      }).catch(function (err) {
        const { warnings, message } = err
        console.log('something went wrong:', warnings, message)
      })
    }
    // const markColor1 = () => {
    //   state.canvas.addMarker('Activity_1w1vj9r', 'highlight')
    // }
    //
    // const markColor2 = () => {
    //   const modeling = state.bpmnModeler.get('modeling')
    //   const elementRegistry = state.bpmnModeler.get('elementRegistry')
    //   var shape = elementRegistry.get('Activity_1149ksn')
    //   modeling.setColor([shape], {
    //     stroke: 'green',
    //     fill: 'red'
    //   })
    // }
    //
    // const markColor3 = () => {
    //   const overlays = state.bpmnModeler.get('overlays')
    //   const elementRegistry = state.bpmnModeler.get('elementRegistry')
    //   const shape2 = elementRegistry.get('Activity_17lsppc')
    //   const layDiv = '<div class="highlight-overlay" style="width: ' + shape2.width + 'px;height: ' + shape2.height + 'px"></div>'
    //   overlays.add(shape2.id, {
    //     position: {
    //       top: 0,
    //       left: 0
    //     },
    //     html: layDiv
    //   })
    // }

    const loadXML = (e) => {
      const file = e.target.files[0]
      const reader = new FileReader()
      reader.readAsText(file)
      reader.onload = function () {
        init(this.result)
      }
    }

    const downloadDiagram = (e) => {
      e.currentTarget.href = 'data:application/bpmn20-xml;charset=UTF-8,' + state.xml
      e.currentTarget.download = new Date().getMilliseconds() + 'diagram.bpmn'
    }

    const downloadSvg = (e) => {
      e.currentTarget.href = 'data:application/bpmn20-xml;charset=UTF-8,' + state.svg
      e.currentTarget.download = new Date().getMilliseconds() + 'diagram.svg'
    }

    const handlerRedo = () => {
      state.bpmnModeler.get('commandStack').redo()
    }
    const handlerUndo = () => {
      state.bpmnModeler.get('commandStack').undo()
    }
    const handlerZoom = (radio) => {
      const newScale = !radio ? 1.0 : state.scale + radio
      state.canvas.zoom(newScale)
      state.scale = newScale
    }

    return {
      ...toRefs(state),
      loadXML,
      downloadDiagram,
      downloadSvg,
      handlerRedo,
      handlerUndo,
      handlerZoom
    }
  }
}
</script>
<style scoped>
  .containers {
    background-color: white;
    overflow: auto;
    background-image: linear-gradient(
      90deg,
      rgba(220, 220, 220, 0.5) 6%,
      transparent 0
    ),
    linear-gradient(rgba(192, 192, 192, 0.5) 6%, transparent 0);
    background-size: 12px 12px;
    width: 100%;
    height: calc(100vh - 60px);
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
  }

  #canvas, #canvas > div {
    width: 100%;
    height: 100%;
  }
  .buttons {
    position: absolute;
    left: 20px;
    bottom: 20px;
  }
  .buttons li {
    display: inline-block;
    margin: 5px;
  }
  .buttons li a {
    color: #333;
    background: #fff;
    cursor: pointer;
    padding: 8px;
    border: 1px solid #ccc;
    text-decoration: none;
  }
</style>
